import React, { useEffect, useState, useMemo } from 'react';
import { connect } from 'react-redux';
import { Row, Col, Tree, Input, Form, Select, InputNumber, Button, message, Tooltip } from 'antd';
import FormItem from '../../../../components/FormItem';
import CodeMirror from 'src/components/ScriptEditor';
import services from '../../../../services/api';
import Modal from '../../../../components/Modal';
import { compare, compareClass } from '../../../../utils/compare';
import { cloneDeep } from 'lodash';
import Test from './test';
import DeptSelect from '../../../../components/DeptSelect';
import './index.less';

const layout = {
  labelCol: {
    span: 6,
  },
  wrapperCol: {
    span: 18,
  },
};

const { TreeNode } = Tree;

let testObj = {}; // 向测试组件传递的参数
let defaultTreeData = []; // tree 默认data

const CustomParamAdd = (props) => {
  const { form, actionType, record = {}, value, closeModal, isCompare, depts } = props;
  const [treeData, setTreeData] = useState({});
  const [dataTypeList, setDataTypeList] = useState([]);
  const [data, setData] = useState({});
  const [interfaceGroupOptions, setInterfaceGroupOptions] = useState([]);
  const [interfaceOptions, setInterfaceOptions] = useState([]);

  useEffect(() => {
    getInterfaceGroup();
    getDataTypeList();
    const { group_id, third_list_param_id } = record;
    third_list_param_id && !props.isAuditLog && getParamsDetail(third_list_param_id); // 详情
    group_id && getInterfaceByGroup(group_id); // 根据接口分组获取接口表
  }, []);

  useEffect(() => {
    if (actionType === 'update') {
      interfaceOptions.length && getResourceList(record.third_list_config_id); // 根据接口获取资源列表
    }
  }, [interfaceOptions]);

  // 对比传入的value
  useEffect(() => {
    if (value && Object.keys(value).length) {
      const { group_id } = value;
      group_id && getInterfaceByGroup(group_id); // 根据接口分组获取接口列表
      const tempValue = cloneDeep(value);
      setData(tempValue);
    }
  }, [value]);

  // 获取数据类型
  const getDataTypeList = async () => {
    const { data, code, msg } = await services.customParams.dataTypeList();
    if (!code) {
      setDataTypeList(data);
    } else {
      message.error(msg);
    }
  };

  // 获取接口分组的列表 - 新增
  const getInterfaceGroup = async () => {
    const { data, code } = await (actionType === 'add'
      ? services.customParams.interfaceGroupList()
      : services.outerList.interfaceGroupList());
    if (!code) setInterfaceGroupOptions(data);
  };

  const handleGroupChange = (value) => {
    form.setFieldsValue({ third_list_config_id: '' });
    value && getInterfaceByGroup(value);
  };

  // 根据接口分组获取接口
  const getInterfaceByGroup = async (group_id) => {
    const { data, code } = await (actionType === 'add'
      ? services.customParams.getInterfaceByGroup({ group_id })
      : services.outerList.getNameList({ group_id }));
    if (!code) setInterfaceOptions(data);
  };

  // 获取详情
  const getParamsDetail = async (third_list_param_id) => {
    const { data, code, msg } = await services.customParams.detail({ third_list_param_id });
    if (!code) {
      setData(data);
    } else {
      message.error(msg);
    }
  };

  // 选择接口获取参数
  const getResourceList = (third_list_config_id) => {
    testObj['url'] = (interfaceOptions.find((item) => item.third_list_config_id === third_list_config_id) || {}).url;
    services.customParams.getResourceList({ third_list_config_id }).then((res) => {
      const { code, data, msg } = res;
      if (!code) {
        setTreeData(data);
        defaultTreeData = data;
      } else {
        message.error(msg);
      }
    });
  };

  // tree搜索
  const handleTreeSearch = (value) => {
    const findValue = (obj) => {
      let child = {};
      for (let key in obj) {
        if (typeof obj[key] === 'string' && obj[key].includes(value)) {
          child = obj;
        } else if (key.includes(value)) {
          child[key] = obj[key];
        } else if (typeof obj[key] === 'object') {
          const childObj = findValue(obj[key]);
          if (Object.keys(childObj).length) {
            child[key] = childObj;
          }
        }
      }
      return child;
    };
    setTreeData(findValue(treeData));
  };

  const handleTreeChange = (value) => {
    if (!value) setTreeData(defaultTreeData);
  };

  const loop = (data) => {
    const treeData = [];
    for (let key in data) {
      const loopObj = data[key];
      if (loopObj.level_right !== false) {
        treeData.push(
          <TreeNode key={key} title={key}>
            {loop(loopObj)}
          </TreeNode>
        );
      } else {
        treeData.push(
          <TreeNode
            key={key}
            title={
              <Tooltip placement='top' title={`参数名称：${loopObj.name}, 数据类型: ${loopObj.data_type}`}>
                {loopObj.code}
              </Tooltip>
            }
          />
        );
      }
    }
    return treeData;
  };

  //  tree 会有两种格式 字段结构均不一样
  const renderLeftNodes = () => (
    <>
      <Input.Search
        style={{ marginBottom: 8 }}
        placeholder='请搜索'
        onSearch={handleTreeSearch}
        onChange={(e) => handleTreeChange(e.target.value)}
      />
      <Tree>{loop(treeData)}</Tree>
    </>
  );

  const handleTest = () => {
    form.validateFields((errors, values) => {
      if (!errors) {
        const key = Modal.open({
          title: '测试',
          width: '1000px',
          content: <Test closeModal={() => Modal.close(key)} value={{ ...testObj, ...values }} />,
          isOkBtn: false,
          isCancelBtn: false,
        });
      }
    });
  };

  const DeptSelectNode = useMemo(
    () =>
      DeptSelect({
        treeCheckable: true, // 是否多选
        treeCheckStrictly: true, // 多选时是否取消父子关联
        deptTree: depts, // 全部部门数据
        deptArr: {
          ids: data.dept_access_id || [],
          name: data.deptAccess || [],
        }, // 当前部门数据
        hasRight: true, // 是否需要权限展示
        // nodeDisabled: (item) => !item.dept_id, // 节点禁选
        disabled: actionType === 'detail',
        layout: {
          label: '可见部门',
          ...layout,
        },
        name: 'dept_access_id',
        className: compareClass(props, 'dept_access_id'),
        form: form,
      }),
    [data.dept_access_id, data.deptAccess]
  );

  const getFormItems = () => {
    const {
      group_id,
      third_list_config_id,
      name,
      code,
      data_type,
      max_length = 64,
      remark,
      return_value,
      script,
      error_value,
    } = data;
    return [
      {
        label: {
          label: '接口分组',
          ...layout,
        },
        name: 'group_id',
        options: {
          initialValue: group_id,
          rules: [
            {
              required: true,
              message: '请选择接口分组',
            },
          ],
        },
        component: (
          <Select
            placeholder='请选择接口分组'
            style={{ width: '100%', ...compare(props, 'group_id') }}
            disabled={actionType === 'update' || actionType === 'detail'}
            onChange={handleGroupChange}
          >
            {interfaceGroupOptions.map((item) => (
              <Select.Option value={item.id} key={item.id}>
                {item.name}
              </Select.Option>
            ))}
          </Select>
        ),
      },
      {
        label: {
          label: '所属接口',
          ...layout,
        },
        name: 'third_list_config_id',
        options: {
          initialValue: third_list_config_id,
          rules: [
            {
              required: true,
              message: '请选择所属接口',
            },
          ],
        },
        component: (
          <Select
            placeholder='请选择所属接口'
            style={{ width: '100%', ...compare(props, 'third_list_config_id') }}
            disabled={actionType === 'update' || actionType === 'detail'}
            onChange={(value) => value && getResourceList(value)}
          >
            {interfaceOptions.map((item) => (
              <Select.Option value={item.third_list_config_id} key={item.third_list_config_id}>
                {item.name}
              </Select.Option>
            ))}
          </Select>
        ),
      },
      {
        label: {
          label: '字段名称',
          ...layout,
        },
        name: 'name',
        options: {
          initialValue: name,
          rules: [
            { required: true, message: '请填写字段名称' },
            { max: 128, message: '最长128个字符' },
            { pattern: /^[\u4E00-\u9FA5_a-zA-Z0-9]+$/, message: '限中英文数字下划线' },
          ],
        },
        component: (
          <Input placeholder='请填写字段名称' disabled={actionType === 'detail'} style={compare(props, 'name')} />
        ),
      },
      {
        label: {
          label: '字段CODE',
          ...layout,
        },
        name: 'code',
        options: {
          initialValue: code,
          rules: [
            { required: true, message: '请填写字段CODE' },
            { max: 128, message: '最长128个字符' },
            { pattern: /^[a-zA-Z][_a-zA-Z0-9]*$/, message: '限英文数字下划线，并以英文开头' },
          ],
        },
        component: (
          <Input
            placeholder='请填写字段CODE'
            disabled={actionType === 'update' || actionType === 'detail'}
            style={compare(props, 'code')}
          />
        ),
      },
      {
        label: {
          label: '数据类型',
          ...layout,
        },
        name: 'data_type',
        options: {
          initialValue: data_type,
          rules: [
            {
              required: true,
              message: '请选择数据类型',
            },
          ],
        },
        component: (
          <Select
            placeholder='请选择数据类型'
            style={{ width: '100%', ...compare(props, 'data_type') }}
            disabled={actionType === 'detail'}
          >
            {dataTypeList.map((item) => (
              <Select.Option value={item.code} key={item.code}>
                {item.name}
              </Select.Option>
            ))}
          </Select>
        ),
      },
      {
        label: {
          label: '最大长度',
          ...layout,
        },
        name: 'max_length',
        options: {
          initialValue: max_length,
          rules: [
            {
              required: true,
              message: '请填写最大长度',
            },
          ],
        },
        component: (
          <InputNumber
            placeholder='请填写最大长度'
            min={0}
            style={{ width: '100%', ...compare(props, 'max_length') }}
            disabled={actionType === 'detail'}
          />
        ),
      },
      {
        label: {
          label: '缺失默认值',
          ...layout,
        },
        name: 'return_value',
        options: {
          initialValue: return_value,
          rules: [
            {
              required: true,
              message: '请填写缺失默认值',
            },
            {
              max: 128,
              message: '最长128个字符',
            },
          ],
        },
        component: (
          <Input
            placeholder='请填写缺失默认值'
            disabled={actionType === 'detail'}
            style={compare(props, 'return_value')}
          />
        ),
      },
      {
        label: {
          label: '拉取异常值',
          ...layout,
        },
        name: 'error_value',
        options: {
          initialValue: error_value,
          rules: [
            {
              required: true,
              message: '请填写拉取异常值',
            },
            {
              max: 128,
              message: '最长128个字符',
            },
          ],
        },
        component: (
          <Input
            placeholder='请填写拉取异常值'
            disabled={actionType === 'detail'}
            style={compare(props, 'error_value')}
          />
        ),
      },
      DeptSelectNode,
      {
        label: {
          label: '描述',
          ...layout,
        },
        name: 'remark',
        options: {
          initialValue: remark,
          rules: [
            {
              max: 256,
              message: '最长256个字符',
            },
          ],
        },
        component: <Input disabled={actionType === 'detail'} style={compare(props, 'remark')} />,
      },
      {
        label: {
          label: '计算脚本',
          className: 'script',
          labelCol: {
            span: 24,
          },
          wrapperCol: {
            span: 24,
          },
        },
        name: 'script',
        options: {
          initialValue: script,
          rules: [
            {
              required: true,
              message: '请填写计算脚本',
            },
          ],
        },
        component: <CodeMirror disabled={actionType === 'detail'} />,
        after: !isCompare && <span onClick={handleTest}>测试</span>,
      },
    ];
  };

  const handleSubmit = () => {
    form.validateFields(async (errors, values) => {
      if (!errors) {
        const { third_list_param_id } = record;
        values.dept_access_id = values.dept_access_id.map((item) => item.value);
        const { code, msg } = await services.customParams[actionType]({
          ...values,
          third_list_param_id,
        });
        if (!code) {
          message.success(msg);
          closeModal();
        } else {
          message.error(msg);
        }
      }
    });
  };

  return (
    <Form className='custom-params'>
      <Row type='flex' className='params' gutter={20}>
        {actionType !== 'detail' && !isCompare && (
          <Col span={6} className='params_left'>
            {renderLeftNodes()}
          </Col>
        )}
        <Col span={actionType !== 'detail' && !isCompare ? 18 : 24} className='params_right'>
          <Row type='flex' gutter={20}>
            {getFormItems().map((item, index) => (
              <Col span={index === getFormItems().length - 1 ? 24 : 12} key={item.name}>
                <FormItem {...props} form={form} item={item} colNum={1} />
              </Col>
            ))}
          </Row>
          {!isCompare && (
            <Row Row type='flex' justify='end' align='middle' className='params_button'>
              <Button onClick={closeModal} style={{ marginRight: '20px' }}>
                取消
              </Button>
              {actionType !== 'detail' && (
                <Button type='primary' onClick={handleSubmit}>
                  确定
                </Button>
              )}
            </Row>
          )}
        </Col>
      </Row>
    </Form>
  );
};
function mapStateToProps(state) {
  return {
    depts: state.global.depts,
  };
}

export default connect(mapStateToProps)(Form.create()(CustomParamAdd));
